package com.youlu.campus.service.activity.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.ActivityRewardRule;
import com.youlu.campus.entity.ActivityTaskInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.VO.req.ActivityRewardRuleQueryVO;
import com.youlu.campus.entity.VO.req.CopyTaskRuleReq;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.service.activity.ActivityRewardRuleService;
import com.youlu.campus.service.activity.ActivityTaskService;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.backoff.BackOff;

import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ActivityRewardRuleServiceImpl implements ActivityRewardRuleService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ActivityTaskService activityTaskService;
    @Autowired
    private MapperFacade mapperFacade;

    @Override
    public Page<ActivityRewardRule> list(ActivityRewardRuleQueryVO request) {
        log.info(":>>> 开始获取活动奖励规则列表:{}", JSON.toJSONString(request));
        if (Objects.isNull(request) || StringUtils.isBlank(request.getTaskId())) {
            log.error(":>>> 任务ID为空");
            throw new BusinessException("任务列表参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("taskId").is(request.getTaskId()));
        Long count = mongoTemplate.count(query, ActivityRewardRule.class);
        log.info(":>>> 订单的数量:{}，查询条件:{}", count, JSON.toJSON(query));
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "priority"));
        Sort sort=Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        List<ActivityRewardRule> orderPOS = mongoTemplate.find(query.with(pageRequest), ActivityRewardRule.class);
        final Long c = count;
        return PageableExecutionUtils.getPage(orderPOS, pageRequest, () -> c);
    }

    @Override
    public ActivityRewardRule findOne(String id) {
        log.info(":>>> 开始获取活动规则:{}", id);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityRewardRule rewardRule = mongoTemplate.findOne(query, ActivityRewardRule.class);
        return rewardRule;
    }

    @Override
    public boolean create(ActivityRewardRule req) {
        if (Objects.isNull(req) || StringUtils.isBlank(req.getTaskId())) {
            log.error(":>>> 新增任务规则错误");
            throw new BusinessException("新增任务规则错误");
        }
        ActivityTaskInfo taskInfo = activityTaskService.findOne(req.getTaskId());
        req.setCreatedTime(new Date());
        req.setId(null);
        req.setActivityId(taskInfo.getActivityId());
        req.setTaskName(taskInfo.getName());
        checkTips(req.getTips(), req.getReplaced());
        mongoTemplate.insert(req);
        return true;
    }

    @Override
    public boolean update(ActivityRewardRule req) {
        log.info(":>>> 开始修改证书规则:{},", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getTaskId()) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 修改活动规则失败:参数错误");
            throw new BusinessException("修改活动规则失败:参数错误");
        }
        this.checkTips(req.getTips(), req.getReplaced());
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getOrgCaName())) {
            update.set("orgCaName", req.getOrgCaName());
        }
        if (StringUtils.isNotBlank(req.getCaName())) {
            update.set("caName", req.getCaName());
        }
        if (Objects.nonNull(req.getOrderNo())) {
            update.set("orderNo", req.getOrderNo());
        }
        if (Objects.nonNull(req.getPriority())) {
            update.set("priority", req.getPriority());
        }
        if (Objects.nonNull(req.getOrderTotal())) {
            update.set("orderTotal", req.getOrderTotal());
        }
        if (Objects.nonNull(req.getOffLineStatus())) {
            update.set("offLineStatus", req.getOffLineStatus());
        }
        if (Objects.nonNull(req.getNextCaQ())) {
            update.set("nextCaQ", req.getNextCaQ());
        }
        if (Objects.nonNull(req.getReplaced())) {
            update.set("replaced", req.getReplaced());
        }
        if (Objects.nonNull(req.getInviteEnd())) {
            update.set("inviteEnd", req.getInviteEnd());
        }
        if (Objects.nonNull(req.getInviteStart())) {
            update.set("inviteStart", req.getInviteStart());
        }
        if (Objects.nonNull(req.getInviteEqu())) {
            update.set("inviteEqu", req.getInviteEqu());
        }
        if (Objects.nonNull(req.getQaStatus())) {
            update.set("qaStatus", req.getQaStatus());
        }
        if (Objects.nonNull(req.getBoon())) {
            update.set("boon", req.getBoon());
        }
        if (Objects.nonNull(req.getDesc())) {
            update.set("desc", req.getDesc());
        }
        if (Objects.nonNull(req.getNextCaQ())) {
            update.set("nextCaQ", req.getNextCaQ());
        }
        if (Objects.nonNull(req.getNextCaName())) {
            update.set("nextCaName", req.getNextCaName());
        }
        if (Objects.nonNull(req.getInviteOperatorType())) {
            update.set("inviteOperatorType", req.getInviteOperatorType());
        }
        if (Objects.nonNull(req.getReplacedCa())) {
            update.set("replacedCa", req.getReplacedCa());
        }
        if (Objects.nonNull(req.getTips())) {
            update.set("tips", req.getTips());
        }
        if (StringUtils.isNotBlank(req.getInviteNumTips())) {
            update.set("inviteNumTips", req.getInviteNumTips());
        }
        if (Objects.nonNull(req.getUnit())) {
            update.set("unit", req.getUnit());
        }
        if (Objects.nonNull(req.getVolunteerDuration())) {
            update.set("volunteerDuration", req.getVolunteerDuration());
        }
        if (Objects.nonNull(req.getReplaced())) {
            update.set("replaced", req.getReplaced());
        }
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ActivityRewardRule.class);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public boolean delete(String tenantId, String id) {
        log.info(":>>> 开始删除证书规则:{},{}", tenantId, id);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        DeleteResult deleteResult = mongoTemplate.remove(query, ActivityRewardRule.class);
        return deleteResult.getDeletedCount() > 0 ? true : false;
    }

    @Override
    public ActivityRewardRule match(String activityId, String taskId, Boolean hasQa, Boolean hasOffLine, ActivityRewardRule req) {
        log.info(":>>> 开始匹配奖励规则 activityId:{},taskId:{},hasQa:{},hasOffLine:{},req:{}", activityId, taskId, hasQa, hasOffLine, JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(activityId) || StringUtils.isBlank(taskId) || Objects.isNull(req.getToMatchValue())) {
            log.error(":>>> 奖励规则匹配参数错误:无配置的规则");
            return null;
        }
        Query query = new Query().addCriteria(Criteria.where("activityId").is(activityId).and("taskId").is(taskId));
        query.with(Sort.by(Sort.Order.desc("priority")));
        List<ActivityRewardRule> datas = mongoTemplate.find(query, ActivityRewardRule.class);
        if (CollectionUtils.isEmpty(datas)) {
            log.error(":>>> 奖励规则匹配错误:无配置的规则");
            return null;
        }
        int i = 0;
        for (ActivityRewardRule data : datas) {
            i++;
            log.info(":>>> 开始匹配证书规则序号:{},:{}", i, JSON.toJSON(data));
            boolean todo = true;
            if (Boolean.TRUE.equals(hasQa)) {
                if (Objects.nonNull(data.getQaStatus())&&!req.getQaStatus().equals(data.getQaStatus())) {
                    todo = false;
                }
            }
            if (Boolean.TRUE.equals(hasOffLine)) {
                if (!req.getOffLineStatus().equals(data.getOffLineStatus())) {
                    todo = false;
                }
            }
            log.info(":>>> 匹配规则:{},todo:{}", i, todo);
            if (todo) {
                if (StringUtils.isBlank(data.getInviteOperatorType())) {
                    log.info(":>>>  操作类型为空:{}", data.getId());
                    continue;
                }
                //       section,equals,leftInterval,rightInterval
                //        return (x < y) ? -1 : ((x == y) ? 0 : 1);
                switch (data.getInviteOperatorType()) {
                    case "section":
                        if (Objects.nonNull(data.getInviteStart()) && Objects.nonNull(data.getInviteEnd())) {
                            if ((req.getToMatchValue().compareTo(data.getInviteStart()) != -1) && (req.getToMatchValue().compareTo(data.getInviteEnd()) != 1)) {
                                log.info(":>>> 匹配上规则:{}", JSON.toJSONString(data));
                                return data;
                            } else {
                                log.error(":>>> 规则配置错误:{} 没有匹配", data.getId());
                            }
                        }
                        break;
                    case "equals":
                        if (Objects.nonNull(data.getInviteEqu())) {
                            if (req.getToMatchValue().compareTo(data.getInviteEqu()) == 0) {
                                log.info(":>>> 匹配上规则:{}", JSON.toJSONString(data));
                                return data;
                            }
                        }
                        break;
                    case "leftInterval":
                        if (Objects.nonNull(data.getInviteStart())) {
                            if (req.getToMatchValue().compareTo(data.getInviteStart()) != 1) {
                                log.info(":>>> 匹配上规则:{}", JSON.toJSONString(data));
                                return data;
                            }
                        }
                        break;
                    case "rightInterval":
                        if (Objects.nonNull(data.getInviteEnd())) {
                            if (req.getToMatchValue().compareTo(data.getInviteEnd()) != -1) {
                                log.info(":>>> 匹配上规则:{}", JSON.toJSONString(data));
                                return data;
                            }
                        }
                        break;
                    default:
                        continue;

                }
            }
        }
        log.info(":>>> 没有匹配规则:规则为空");
        return null;
    }

    @Override
    public List<ActivityRewardRule> findByActivityId(String activityId) {

        ActivityTaskInfo activityTaskInfo = activityTaskService.find(activityId, TaskBizType.INVITE);
        if(Objects.isNull(activityTaskInfo)){
            return null;
        }
        Query query = new Query().addCriteria(Criteria.where("activityId").is(activityId).and("taskId").is(activityTaskInfo.getId()));
        query.with(Sort.by(Sort.Order.desc("priority")));
        return mongoTemplate.find(query, ActivityRewardRule.class);
    }

    @Async
    @Override
    public void doCopyActivityRewardRule(CopyTaskRuleReq copyTaskRuleReq) {
        String copyActivityId = copyTaskRuleReq.getCopyActivityId();
        String copyTaskId = copyTaskRuleReq.getCopyTaskId();
        String bizType = copyTaskRuleReq.getBizType();
        String targetCopyActivityId = copyTaskRuleReq.getTargetCopyActivityId();
        String targetCopyTaskId = copyTaskRuleReq.getTargetCopyTaskId();
        log.info("【copy 活动】开始复制活动邀请任务规则 ->{} taskId ->{}",copyActivityId,copyTaskId);
        Query query = new Query().addCriteria(Criteria.where("activityId").is(copyActivityId).and("taskId").is(copyTaskId));
        List<ActivityRewardRule> rewardRuleList = this.mongoTemplate.find(query, ActivityRewardRule.class);
        if(CollectionUtils.isEmpty(rewardRuleList)){
            log.error("【copy 活动-邀请任务规则】未查询到复制活动邀请任务规则 ->{} taskId ->{}",copyActivityId,copyTaskId);
            return;
        }
        Date now = new Date();
        rewardRuleList.stream().forEach(activityRewardRule -> {
            ActivityRewardRule targetActivityRewardRule = mapperFacade.map(activityRewardRule, ActivityRewardRule.class);
            targetActivityRewardRule.setId(null);
            targetActivityRewardRule.setActivityId(targetCopyActivityId);
            targetActivityRewardRule.setTaskId(targetCopyTaskId);
            targetActivityRewardRule.setCreatedTime(now);
            targetActivityRewardRule.setUpdatedTime(now);
            this.mongoTemplate.save(targetActivityRewardRule);
        });
        log.info("【copy 活动】结束复制活动邀请任务规则 ->{} taskId ->{}",copyActivityId,copyTaskId);

    }

    private void checkTips(String tips, Boolean replaced) {
        if (StringUtils.isBlank(tips)) {
            log.error(":>>> 提示语配置错误:提示语为空");
            throw new BusinessException("提示语配置错误:提示语为空");
        }
        if (Boolean.FALSE.equals(replaced)) {
            return;
        }
        if (!tips.contains("%s") && !tips.contains("%d")) {
            log.error(":>>> 提示语配置错误:提示语需要包含%s,%d");
            throw new BusinessException("提示语需要包含%s,%d");
        }
    }
}
